package com.jxc.wiki.controller;

import com.alibaba.fastjson.JSONObject;
import com.jxc.wiki.request.UserLoginParamReq;
import com.jxc.wiki.request.UserQueryParamReq;
import com.jxc.wiki.request.UserResetPasswordParamReq;
import com.jxc.wiki.request.UserSaveParamReq;
import com.jxc.wiki.response.CommonResp;
import com.jxc.wiki.response.PageParamResp;
import com.jxc.wiki.response.UserLoginParamResp;
import com.jxc.wiki.response.UserQueryParamResp;
import com.jxc.wiki.service.UserService;
import com.jxc.wiki.util.SnowFlakeUtil;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Controller;
import org.springframework.util.DigestUtils;
import org.springframework.web.bind.annotation.*;

import javax.annotation.Resource;
import javax.validation.Valid;
import java.util.concurrent.TimeUnit;

@Controller
public class UserController {

    private static final Logger LOG = LoggerFactory.getLogger(UserController.class);

    @Resource
    private UserService userService;

    @Resource
    private StringRedisTemplate stringRedisTemplate;

    @Resource
    private SnowFlakeUtil snowFlakeUtil;

    // 测试get请求
    @RequestMapping("/user/list")
    @ResponseBody
    // @Valid 用来开启校验，防止有人通过脚本修改后端获取的数据数，从而导致服务器崩溃
    public CommonResp<PageParamResp<UserQueryParamResp>> list(@Valid UserQueryParamReq req){
        CommonResp<PageParamResp<UserQueryParamResp>> resp = new CommonResp<>();
        PageParamResp<UserQueryParamResp> list = userService.list(req);
        resp.setContent(list);
        return resp;
    }

    @PostMapping("/user/save")
    @ResponseBody
    // 注意由于axios的post请求提交是用json的格式，所以在参数前要加个@RequestBody，相当于标记数据为application/json格式
    public CommonResp save(@Valid @RequestBody UserSaveParamReq req){
        // 利用spring自带的工具类，对密码进行md5加密变成16进制
        req.setPassword(DigestUtils.md5DigestAsHex(req.getPassword().getBytes()));
        CommonResp resp = new CommonResp<>();
        userService.save(req);
        return resp;
    }


    @DeleteMapping("/user/delete/{id}")
    @ResponseBody
    public CommonResp<Object> delete(@PathVariable Long id){
        CommonResp<Object> resp = new CommonResp<>();
        userService.delete(id);
        return resp;
    }

    // 测试get请求
    @RequestMapping("/user/search")
    @ResponseBody
    // @Valid 用来开启校验，防止有人通过脚本修改后端获取的数据数，从而导致服务器崩溃
    public CommonResp<PageParamResp<UserQueryParamResp>> search(@Valid UserQueryParamReq req){
        CommonResp<PageParamResp<UserQueryParamResp>> resp = new CommonResp<>();
        PageParamResp<UserQueryParamResp> list = userService.list(req);
        resp.setContent(list);
        return resp;
    }

    // 重置密码接口
    @PostMapping("/user/reset-password")
    @ResponseBody
    // 注意由于axios的post请求提交是用json的格式，所以在参数前要加个@RequestBody，相当于标记数据为application/json格式
    public CommonResp<Object> resetPassword(@Valid @RequestBody UserResetPasswordParamReq req){
        // 利用spring自带的工具类，对密码进行md5加密变成16进制
//        req.setPassword(DigestUtils.md5DigestAsHex(req.getPassword().getBytes()));
        System.out.println(req);
        CommonResp<Object> resp = new CommonResp<>();
        userService.resetPassword(req);
        return resp;
    }

    // 重置密码接口
    @PostMapping("/user/login")
    @ResponseBody
    // 注意由于axios的post请求提交是用json的格式，所以在参数前要加个@RequestBody，相当于标记数据为application/json格式
    public CommonResp<UserLoginParamResp> login(@Valid @RequestBody UserLoginParamReq req){
        // 利用spring自带的工具类，对密码进行md5加密变成16进制
//        req.setPassword(DigestUtils.md5DigestAsHex(req.getPassword().getBytes()));
        CommonResp<UserLoginParamResp> resp = new CommonResp<>();
        UserLoginParamResp userLoginParamResp = userService.login(req);
        // 利用雪花算法生成token（token用任何工具类生成都可以，只要是唯一的就行，比如UUID）
        Long token = snowFlakeUtil.nextId();
        LOG.info("生成单点登录token：{}，并放入redis中", token);
        userLoginParamResp.setToken(token);
        // 将token放到redis里面去,ops就是操作的意思,opsForValue().set就是往redis放入一个值
        // 使用stringRedisTemplate来操作redis 可以避免在其他客户端获取时的乱码 【序列化机制问题】
        stringRedisTemplate.opsForValue().set(Long.toString(token), JSONObject.toJSONString(userLoginParamResp),
                3600 * 24, TimeUnit.SECONDS);
        resp.setContent(userLoginParamResp);
        return resp;
    }

    // 退出登录接口
    @GetMapping("/user/logout/{token}")
    @ResponseBody
    public CommonResp<Object> logout(@PathVariable String token){
        CommonResp<Object> resp = new CommonResp<>();
        userService.logout(token);
        return resp;
    }
}
